package me.chyxion.spring.ext.exeptions;

import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.Order;
import org.springframework.dao.*;
import me.chyxion.spring.ext.DataModel;
import org.springframework.web.bind.MissingServletRequestParameterException;

/**
 * @version 0.0.1
 * @since 0.0.3
 * @author Shaun Chyxion <br />
 * chyxion@163.com <br />
 * Feb 3, 2015 2:06:58 PM
 */
@Order(64)
public class DefaultExceptionResolver implements ExceptionResolver {
	private static final Map<Class<? extends Throwable>, Integer> EXCEPTIONS_MAP = 
			new HashMap<Class<? extends Throwable>, Integer>() {
		private static final long serialVersionUID = 1L;
		{
			// Database Exceptions
			put(CannotAcquireLockException.class, 5030);
			put(CannotSerializeTransactionException.class, 5031);
			put(CleanupFailureDataAccessException.class, 5032);
			put(ConcurrencyFailureException.class, 5033);
			put(DataAccessException.class, 5034);
			put(DataAccessResourceFailureException.class, 5035);
			put(DataIntegrityViolationException.class, 5036);
			put(DataRetrievalFailureException.class, 5037);
			put(DeadlockLoserDataAccessException.class, 5038);
			put(DuplicateKeyException.class, 5039);
			put(EmptyResultDataAccessException.class, 5040);
			put(IncorrectResultSizeDataAccessException.class, 5041);
			put(IncorrectUpdateSemanticsDataAccessException.class, 5042);
			put(InvalidDataAccessApiUsageException.class, 5043);
			put(InvalidDataAccessResourceUsageException.class, 5044);
			put(NonTransientDataAccessException.class, 5045);
			put(NonTransientDataAccessResourceException.class, 5046);
			put(OptimisticLockingFailureException.class, 5047);
			put(PermissionDeniedDataAccessException.class, 5048);
			put(PessimisticLockingFailureException.class, 5049);
			put(QueryTimeoutException.class, 5050);
			put(RecoverableDataAccessException.class, 5051);
			put(TransientDataAccessException.class, 5052);
			put(TransientDataAccessResourceException.class, 5053);
			put(TypeMismatchDataAccessException.class, 5054);
			put(UncategorizedDataAccessException.class, 5055);

            // Parameter Validate
			put(InvalidParamException.class, InvalidParamException.CODE);
            put(MissingServletRequestParameterException.class, InvalidParamException.CODE);
		}
	};

	/* (non-Javadoc)
	 * @see me.chyxion.spring.ext.exeptions.ExceptionResolver#accept(java.lang.Throwable)
	 */
	@Override
	public boolean accept(Throwable ex) {
		return true;
	}

	/* (non-Javadoc)
	 * @see me.chyxion.spring.ext.exeptions.ExceptionResolver#process(me.chyxion.spring.ext.DataModel)
	 */
	@Override
	public DataModel process(DataModel model) {
		Object code = model.getCode();
		if (code == null || 
			(code instanceof Number && ((Number) code).intValue() == 0) ||
			(code instanceof String && StringUtils.isBlank((String) code))) {
			code = EXCEPTIONS_MAP.get(model.getException().getClass());
			if (code == null) {
				code = BaseException.CODE;
			}
			model.setCode(code);
		}
		if (model.getMessage() == null) {
			model.setMessage(model.getException().getMessage());
		}
		return model;
	}
}
